home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / Orpheus v3.02 / SETUP.EXE / %MAINDIR% / Ovcbtnhd.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-02-25  |  24.5 KB  |  902 lines

  1. {*********************************************************}
  2. {*                  OVCBTNHD.PAS 3.00                    *}
  3. {*     Copyright (c) 1995-99 TurboPower Software Co      *}
  4. {*                 All rights reserved.                  *}
  5. {*********************************************************}
  6.  
  7. {$I OVC.INC}
  8.  
  9. {$B-} {Complete Boolean Evaluation}
  10. {$I+} {Input/Output-Checking}
  11. {$P+} {Open Parameters}
  12. {$T-} {Typed @ Operator}
  13. {$W-} {Windows Stack Frame}
  14. {$X+} {Extended Syntax}
  15.  
  16. {$IFNDEF Win32}
  17. {$G+} {286 Instructions}
  18. {$N+} {Numeric Coprocessor}
  19.  
  20. {$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
  21. {$ENDIF}
  22.  
  23. unit OvcBtnHd;
  24.   {-Button header component}
  25.  
  26. interface
  27.  
  28. uses
  29.   {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  30.   Buttons, Classes, Controls, Dialogs, ExtCtrls, Forms,
  31.   Graphics, Menus, Messages, SysUtils,
  32.   {$IFNDEF Win32} OvcImLst, {$ENDIF}
  33.   OvcBase, OvcConst, OvcData, OvcMisc;
  34.  
  35. type
  36.   TOvcButtonHeaderStyle = (bhsNone, bhsRadio, bhsButton);
  37.   {$IFDEF Win32}
  38.   TOvcBHDrawingStyle = (bhsDefault, bhsThin, bhsFlat, bhsEtched);
  39.   {$ENDIF}
  40.   TOvcButtonHeaderSection = class(TOvcCollectible)
  41.   {.Z+}
  42.   protected {private}
  43.     {property variables}
  44.     FAlignment  : TAlignment;
  45.     FCaption    : string;
  46.     FImageIndex : Integer;
  47.     FPaintRect  : TRect;
  48.     FWidth      : Integer;
  49.  
  50.   protected
  51.     {property methods}
  52.     procedure SetAlignment(Value : TAlignment);
  53.     procedure SetCaption(const Value : string);
  54.     procedure SetImageIndex(Value : Integer);
  55.     procedure SetWidth(Value : Integer);
  56.  
  57.     function GetBaseName : string;
  58.       override;
  59.     function GetDisplayText : string;
  60.       override;
  61.  
  62.   public
  63.     constructor Create(AOwner : TComponent);
  64.       override;
  65.     property PaintRect : TRect
  66.       read fPaintRect;
  67.  
  68.   published
  69.   {.Z-}
  70.     property Alignment : TAlignment
  71.       read FAlignment write SetAlignment
  72.       default taLeftJustify;
  73.     property Caption : string
  74.       read FCaption write SetCaption;
  75.     property ImageIndex : Integer
  76.       read FImageIndex write SetImageIndex
  77.       default -1;
  78.     property Width : Integer
  79.       read FWidth write SetWidth
  80.       default 75;
  81.   end;
  82.  
  83.   TOvcTextAttrEvent = procedure(Sender : TObject; Canvas : TCanvas; Index : Integer)
  84.     of object;
  85.  
  86.   TOvcButtonHeader = class(TOvcCustomControl)
  87.   {.Z+}
  88.   protected {private}
  89.     {property variables}
  90.     FAllowResize    : Boolean;
  91.     FBorderStyle    : TBorderStyle;
  92.     {$IFDEF Win32}
  93.     FDrawingStyle   : TOvcBHDrawingStyle;
  94.     {$ENDIF}
  95.     FImages         : TImageList;
  96.     FItemIndex      : Integer;
  97.     FPushRect       : TRect;
  98.     FSections       : TOvcCollection;
  99.     FStyle          : TOvcButtonHeaderStyle;
  100.     FTextMargin     : Integer;
  101.     FWordWrap       : Boolean;
  102.  
  103.     {event variables}
  104.     FOnChangeTextAttr : TOvcTextAttrEvent;
  105.     FOnClick        : TNotifyEvent;
  106.     FOnSized        : TSectionEvent;
  107.     FOnSizing       : TSectionEvent;
  108.  
  109.     {internal variables}
  110.     bhCanResize     : Boolean;
  111.     bhHitTest       : TPoint;
  112.     bhMouseOffset   : Integer;
  113.     bhResizeSection : Integer;
  114.     bhSectionPressed: Integer;
  115.     bhDraw          : TBitMap;
  116.  
  117.     SectionChanged  : Boolean;
  118.  
  119.     {property methods}
  120.     function GetWidth(X : Integer) : Integer;
  121.     function GetSection(Index : Integer) : TOvcButtonHeaderSection;
  122.     function GetSectionCount : Integer;
  123.     procedure SetBorderStyle(Value : TBorderStyle);
  124.     {$IFDEF Win32}
  125.     procedure SetDrawingStyle(const Value: TOvcBHDrawingStyle);
  126.     {$ENDIF}
  127.     procedure SetImages(Value : TImageList);
  128.     procedure SetItemIndex(Value : Integer);
  129.     procedure SetSection(Index : Integer; Value : TOvcButtonHeaderSection);
  130.     procedure SetTextMargin(Value : Integer);
  131.     procedure SetWordWrap(Value : Boolean);
  132.     procedure SetStyle(Value : TOvcButtonHeaderStyle);
  133.  
  134.     {internal methods}
  135.     procedure bhCollectionChanged(Sender : TObject);
  136.     procedure bhGetEditorCaption(var Caption : string);
  137.  
  138.     {VCL control methods}
  139.     procedure CMDialogChar(var Msg : TCMDialogChar);
  140.       message CM_DIALOGCHAR;
  141.     procedure CMDesignHitTest(var Msg : TCMDesignHitTest);
  142.       message CM_DESIGNHITTEST;
  143.  
  144.     {windows message response methods}
  145.     procedure WMSetCursor(var Msg : TWMSetCursor);
  146.       message WM_SETCURSOR;
  147.     procedure WMNCHitTest(var Msg : TWMNCHitTest);
  148.       message WM_NCHITTEST;
  149.  
  150.   protected
  151.     procedure CreateParams(var Params : TCreateParams);
  152.       override;
  153.     procedure MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
  154.       override;
  155.     procedure MouseMove(Shift : TShiftState; X, Y : Integer);
  156.       override;
  157.     procedure MouseUp(Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
  158.       override;
  159.     procedure Notification(AComponent : TComponent; Operation: TOperation);
  160.       override;
  161.     procedure Paint;
  162.       override;
  163.  
  164.     procedure DoOnChangeTextAttr(Canvas : TCanvas;Index : Integer);
  165.       dynamic;
  166.     procedure DoOnClick;
  167.       virtual;
  168.     procedure DoOnSized(ASection, AWidth : Integer);
  169.       dynamic;
  170.     procedure DoOnSizing(ASection, AWidth : Integer);
  171.       dynamic;
  172.  
  173.   public
  174.     constructor Create(AOwner : TComponent);
  175.       override;
  176.     destructor Destroy;
  177.       override;
  178.   {.Z-}
  179.  
  180.     {public properties}
  181.   {.Z+}
  182.     property PushRect : TRect read fPushRect;
  183.   {.Z-}
  184.     property Section[Index : Integer] : TOvcButtonHeaderSection
  185.       read GetSection write SetSection;
  186.     property SectionCount : Integer
  187.       read GetSectionCount;
  188.  
  189.   published
  190.     {properties}
  191.     property AllowResize : Boolean
  192.                    read FAllowResize write FAllowResize
  193.                    default True;
  194.     property BorderStyle : TBorderStyle
  195.                    read FBorderStyle write SetBorderStyle
  196.                    default bsNone;
  197.     {$IFDEF Win32}
  198.     property DrawingStyle : TOvcBHDrawingStyle
  199.                    read FDrawingStyle write SetDrawingStyle
  200.                    default bhsDefault;
  201.     {$ENDIF}
  202.     property Images : TImageList
  203.                    read FImages write SetImages;
  204.     property ItemIndex : Integer
  205.                    read FItemIndex write SetItemIndex;
  206.     property LabelInfo;
  207.     property Sections : TOvcCollection
  208.                    read FSections write FSections;
  209.     property Style : TOvcButtonHeaderStyle
  210.                    read FStyle write SetStyle
  211.                    default bhsRadio;
  212.     property TextMargin : Integer
  213.                    read FTextMargin write SetTextMargin
  214.                    default 0;
  215.     property WordWrap : Boolean
  216.                    read FWordWrap write SetWordWrap
  217.                    default False;
  218.  
  219.     {events}
  220.     property OnClick : TNotifyEvent
  221.                    read FOnClick write FOnClick;
  222.     property OnSizing : TSectionEvent
  223.                    read FOnSizing write FOnSizing;
  224.     property OnSized : TSectionEvent
  225.                    read FOnSized write FOnSized;
  226.  
  227.     {inherited properties}
  228.     {$IFDEF VERSION4}
  229.     property Anchors;
  230.     property Constraints;
  231.     {$ENDIF}
  232.     property Align;
  233.     property Enabled;
  234.     property Font;
  235.     property ParentFont;
  236.     property ParentShowHint;
  237.     property PopupMenu;
  238.     property ShowHint;
  239.     property TabOrder;
  240.     property TabStop;
  241.     property Visible;
  242.     {inherited events}
  243.     property OnMouseDown;
  244.     property OnMouseMove;
  245.     property OnMouseUp;
  246.   end;
  247.  
  248.  
  249. implementation
  250.  
  251.  
  252. {*** TOvcButtonHeaderSection ***}
  253.  
  254. constructor TOvcButtonHeaderSection.Create(AOwner : TComponent);
  255. begin
  256.   inherited Create(AOwner);
  257.  
  258.   FAlignment := taLeftJustify;
  259.   FImageIndex := -1;
  260.   FWidth := 75;
  261. end;
  262.  
  263. function TOvcButtonHeaderSection.GetBaseName : string;
  264. begin
  265.   Result := GetOrphStr(SCSectionBaseName);
  266. end;
  267.  
  268. function TOvcButtonHeaderSection.GetDisplayText : string;
  269.  
  270.   function TrimAmpersand(const S : string) : string;
  271.   var
  272.     p : Integer;
  273.   begin
  274.     Result := S;
  275.     p := Pos('&', Result);
  276.     while p <> 0 do begin
  277.       Delete(Result,p,1);
  278.       p := Pos('&',Result);
  279.     end;
  280.   end;
  281.  
  282. begin
  283.   if Caption > '' then
  284.     Result := TrimAmpersand(Caption) + ': ' + ClassName
  285.   else
  286.     Result := Name + ': ' + ClassName;
  287. end;
  288.  
  289. procedure TOvcButtonHeaderSection.SetAlignment(Value : TAlignment);
  290. begin
  291.   if (Value <> FAlignment) then begin
  292.     FAlignment := Value;
  293.     Changed;
  294.   end;
  295. end;
  296.  
  297. procedure TOvcButtonHeaderSection.SetCaption(const Value : string);
  298. begin
  299.   if Value <> Caption then begin
  300.     FCaption := Value;
  301.     Changed;
  302.   end;
  303. end;
  304.  
  305. procedure TOvcButtonHeaderSection.SetImageIndex(Value : Integer);
  306. begin
  307.   if Value <> ImageIndex then begin
  308.     FImageIndex := Value;
  309.     Changed;
  310.   end;
  311. end;
  312.  
  313. procedure TOvcButtonHeaderSection.SetWidth(Value : Integer);
  314. begin
  315.   if Value <> Width then begin
  316.     FWidth := Value;
  317.     Changed;
  318.   end;
  319. end;
  320.  
  321.  
  322. {*** TOvcButtonHeader ***}
  323.  
  324. procedure TOvcButtonHeader.bhCollectionChanged;
  325. begin
  326.   Invalidate;
  327. end;
  328.  
  329. procedure TOvcButtonHeader.bhGetEditorCaption(var Caption : string);
  330. begin
  331.   Caption := GetOrphStr(SCEditingSections);
  332. end;
  333.  
  334. procedure TOvcButtonHeader.CMDialogChar(var Msg : TCMDialogChar);
  335. var
  336.   I : Integer;
  337. begin
  338.   if Enabled then with Msg do begin
  339.     for I := 0 to Pred(FSections.Count) do
  340.     if IsAccel(CharCode, Section[I].Caption) then begin
  341.       ItemIndex := I;
  342.       Result := 1;
  343.       Exit;
  344.     end;
  345.   end;
  346.  
  347.   inherited;
  348. end;
  349.  
  350. procedure TOvcButtonHeader.CMDesignHitTest(var Msg : TCMDesignHitTest);
  351. begin
  352.   if bhCanResize then
  353.     Msg.Result := 1
  354.   else
  355.     inherited;
  356. end;
  357.  
  358. constructor TOvcButtonHeader.Create(AOwner: TComponent);
  359. begin
  360.   inherited Create(AOwner);
  361.  
  362.   if Classes.GetClass(TOvcButtonHeaderSection.ClassName) = nil then
  363.     Classes.RegisterClass(TOvcButtonHeaderSection);
  364.  
  365.   ControlStyle := ControlStyle + [csOpaque];
  366.  
  367.   Width := 250;
  368.   Height := 20;
  369.  
  370.   FSections := TOvcCollection.Create(Self, TOvcButtonHeaderSection);
  371.   FSections.OnChanged := bhCollectionChanged;
  372.   FSections.OnGetEditorCaption := bhGetEditorCaption;
  373.  
  374.   FAllowResize := True;
  375.   FBorderStyle := bsNone;
  376.   FStyle       := bhsRadio;
  377.   FTextMargin  := 0;
  378.   FWordWrap    := False;
  379.  
  380.   bhSectionPressed := -1;
  381. end;
  382.  
  383. procedure TOvcButtonHeader.CreateParams(var Params : TCreateParams);
  384. const
  385.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  386. begin
  387.   inherited CreateParams(Params);
  388.  
  389.   Params.Style := LongInt(Params.Style) or BorderStyles[FBorderStyle];
  390.   {$IFDEF Win32}
  391.   if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then begin
  392.     Params.Style := Params.Style and not WS_BORDER;
  393.     Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
  394.   end;
  395.   {$ENDIF}
  396. end;
  397.  
  398. destructor TOvcButtonHeader.Destroy;
  399. begin
  400.   if FImages <> nil then
  401.     FImages.OnChange := nil;
  402.   FSections.Free;
  403.   FSections := nil;
  404.  
  405.   bhDraw.Free;
  406.   bhDraw := nil;
  407.   inherited Destroy;
  408. end;
  409.  
  410. procedure TOvcButtonHeader.DoOnChangeTextAttr(Canvas : TCanvas; Index : Integer);
  411. begin
  412.   if Assigned(FOnChangeTextAttr) then
  413.     FOnChangeTextAttr(Self, Canvas, Index);
  414. end;
  415.  
  416. procedure TOvcButtonHeader.DoOnClick;
  417. begin
  418.   Invalidate;
  419.   if Assigned(FOnClick) then
  420.     FOnClick(Self);
  421. end;
  422.  
  423. procedure TOvcButtonHeader.DoOnSizing(ASection, AWidth : Integer);
  424. begin
  425.   if Assigned(FOnSizing) then
  426.     FOnSizing(Self, ASection, AWidth);
  427. end;
  428.  
  429. procedure TOvcButtonHeader.DoOnSized(ASection, AWidth : Integer);
  430. begin
  431.   if Assigned(FOnSized) then
  432.     FOnSized(Self, ASection, AWidth);
  433. end;
  434.  
  435. function TOvcButtonHeader.GetSection(Index : Integer) : TOvcButtonHeaderSection;
  436. begin
  437.   Result := TOvcButtonHeaderSection(FSections[Index]);
  438. end;
  439.  
  440. function TOvcButtonHeader.GetSectionCount : Integer;
  441. begin
  442.   Result := FSections.Count;
  443. end;
  444.  
  445. function TOvcButtonHeader.GetWidth(X : Integer) : Integer;
  446. var
  447.   I, W : Integer;
  448. begin
  449.   if X = FSections.Count - 1 then begin
  450.     W := 0;
  451.     for I := 0 to X - 1 do
  452.       Inc(W, Section[I].Width);
  453.     Result := ClientWidth - W;
  454.   end else if (X >= 0) and (X < FSections.Count) then
  455.     Result := Section[X].Width
  456.   else
  457.     Result := 0;
  458. end;
  459.  
  460. procedure TOvcButtonHeader.MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
  461. var
  462.   I,J : Integer;
  463. begin
  464.   SectionChanged := False;
  465.   if bhCanResize then begin
  466.     inherited MouseDown(Button, Shift, X, Y);
  467.     if (Button = mbLeft) then
  468.       SetCapture(Handle);
  469.   end else
  470.     if not (csDesigning in ComponentState) and (Button = mbLeft) then begin
  471.       Y := 2;
  472.       J := -1;
  473.       for I := 0 to FSections.Count - 1 do begin
  474.         Inc(Y, Section[I].Width);
  475.         if Y > X then begin
  476.           J := I;
  477.           Break;
  478.         end;
  479.       end;
  480.       if (J <> -1) and (J < FSections.Count) then begin
  481.         inherited MouseDown(Button, Shift, X, Y);
  482.         case Style of
  483.         bhsRadio :
  484.           begin
  485.             ItemIndex := J;
  486.             Invalidate;
  487.           end;
  488.         bhsButton :
  489.           begin
  490.             bhSectionPressed := J;
  491.             FItemIndex := J;
  492.             Refresh;
  493.           end;
  494.         bhsNone :
  495.           FItemIndex := J;
  496.         end;
  497.         SectionChanged := True;
  498.       end;
  499.     end;
  500. end;
  501.  
  502. procedure TOvcButtonHeader.MouseMove(Shift : TShiftState; X, Y : Integer);
  503. var
  504.   I      : Integer;
  505.   AbsPos : Integer;
  506.   MinPos : Integer;
  507.   MaxPos : Integer;
  508.   InvRect: TRect;
  509. begin
  510.   inherited MouseMove(Shift, X, Y);
  511.  
  512.   if (GetCapture = Handle) and bhCanResize then begin
  513.     {absolute position of this item}
  514.     AbsPos := 2;
  515.     for I := 0 to bhResizeSection do
  516.       Inc(AbsPos, Section[I].Width);
  517.     if bhResizeSection > 0 then MinPos := AbsPos -
  518.       Section[bhResizeSection].Width + 2
  519.     else
  520.       MinPos := 2;
  521.  
  522.     MaxPos := ClientWidth - 2;
  523.     if X < MinPos then
  524.       X := MinPos;
  525.     if X > MaxPos then
  526.       X := MaxPos;
  527.  
  528.     Section[bhResizeSection].Width := Section[bhResizeSection].Width -
  529.       (AbsPos - X - 2) - bhMouseOffset;
  530.     DoOnSizing(bhResizeSection, Section[bhResizeSection].Width);
  531.  
  532.     InvRect.Left := X;
  533.     InvRect.Top := 0;
  534.     InvRect.Bottom := Height-1;
  535.     InvRect.Right := Width-1;
  536.  
  537.     Refresh;
  538.   end;
  539. end;
  540.  
  541. procedure TOvcButtonHeader.MouseUp(Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
  542. begin
  543.   if bhCanResize then begin
  544.     ReleaseCapture;
  545.     DoOnSized(bhResizeSection,
  546.       Section[bhResizeSection].Width);
  547.     bhCanResize := False;
  548.   end else
  549.   case Style of
  550.   bhsButton :
  551.     begin
  552.       bhSectionPressed := -1;
  553.       if SectionChanged then begin
  554.         if PtInRect(ClientRect, Point(X,Y)) then
  555.           DoOnClick;
  556.         Refresh;
  557.       end;
  558.     end;
  559.   bhsNone :
  560.     if SectionChanged then
  561.       if PtInRect(ClientRect, Point(X,Y)) then
  562.         DoOnClick;
  563.   end;
  564.  
  565.   inherited MouseUp(Button, Shift, X, Y);
  566. end;
  567.  
  568. procedure TOvcButtonHeader.Notification(AComponent : TComponent; Operation : TOperation);
  569. begin
  570.   inherited Notification(AComponent, Operation);
  571.  
  572.   if Operation = opRemove then
  573.     if AComponent = FImages then
  574.       Images := nil;
  575. end;
  576.  
  577. procedure TOvcButtonHeader.Paint;
  578. var
  579.   I, W    : Integer;
  580.   P       : array[0..255] of Char;
  581.   S       : string;
  582.   R, R2   : TRect;
  583.   WM, AL  : Word;
  584.   {$IFNDEF WIN32}
  585.   Y       : Integer;
  586.   {$ENDIF}
  587.   Img,H,T : Integer;
  588.   BDim    : TPoint;
  589. begin
  590.   if (bhDraw <> nil) and ((bhDraw.Width <> Width) or (bhDraw.Height <> Height)) then begin
  591.     bhDraw.Free;
  592.     bhDraw := nil;
  593.   end;
  594.   if bhDraw = nil then begin
  595.     bhDraw            := TBitMap.Create;
  596.     bhDraw.Width      := Width;
  597.     bhDraw.Height     := Height;
  598.   end;
  599.  
  600.   with bhDraw.Canvas do begin
  601.     Font := Self.Font;
  602.     Brush.Color := clBtnFace;
  603.     I := 0;
  604.     {$IFNDEF WIN32}
  605.     Y := (ClientHeight - TextHeight('T')) div 2;
  606.     {$ENDIF}
  607.     R := Rect(0, 0, 0, ClientHeight);
  608.     {$IFDEF Win32}
  609.     if (BorderStyle <> bsNone) and (DrawingStyle <> bhsDefault) then
  610.       InflateRect(R,0,1);
  611.     {$ENDIF}
  612.     W := 0;
  613.     repeat
  614.       AL := 0;
  615.       if I < FSections.Count then begin
  616.         with Section[I] do begin
  617.           W := Width;
  618.           case Alignment of
  619.             taLeftJustify  : AL := DT_LEFT;
  620.             taRightJustify : AL := DT_RIGHT;
  621.             taCenter       : AL := DT_CENTER;
  622.           end;
  623.           S := Caption;
  624.           Img := ImageIndex;
  625.           if (Images = nil) or (Img >= Images.Count) then
  626.             Img := -1
  627.         end;
  628.       end else begin
  629.         S := '';
  630.         Img := -1;
  631.       end;
  632.       Inc(I);
  633.       R.Left := R.Right;
  634.       Inc(R.Right, W);
  635.       if (ClientWidth - R.Right < 2) or (I > FSections.Count) then
  636.         R.Right := ClientWidth;
  637.       if I <= SectionCount then
  638.         Section[I-1].fPaintRect := R;
  639.  
  640.       if ((Style = bhsRadio) and (FItemIndex = I-1))
  641.       or ((Style = bhsButton) and (bhSectionPressed = I-1)) then begin
  642.         fPushRect := R;
  643.         {$IFDEF WIN32}
  644.         case DrawingStyle of
  645.         bhsDefault :
  646.           DrawFrameControl(Handle, R, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED);
  647.         bhsThin :
  648.           DrawEdge(bhDraw.Canvas.Handle, R, EDGE_SUNKEN, BF_BOTTOM or BF_TOP or BF_LEFT or BF_RIGHT or BF_MIDDLE);
  649.         bhsFlat :
  650.           begin
  651.             inc(R.Right, 2);
  652.             DrawEdge(bhDraw.Canvas.Handle, R, EDGE_SUNKEN, BF_BOTTOM or BF_TOP or BF_LEFT or BF_RIGHT or BF_MIDDLE);
  653.             dec(R.Right, 2);
  654.           end;
  655.         bhsEtched :
  656.           begin
  657.             inc(R.Right, 2);
  658.             DrawEdge(bhDraw.Canvas.Handle, R, EDGE_SUNKEN, BF_LEFT or BF_RIGHT or BF_BOTTOM or BF_TOP or BF_MIDDLE);
  659.             dec(R.Right, 2);
  660.           end;
  661.         end;
  662.         {$ELSE}
  663.         DrawButtonFrame(bhDraw.Canvas,R,True,False,bsNew);
  664.         {$ENDIF}
  665.       end else
  666.       if Style <> bhsNone then begin
  667.         {$IFDEF WIN32}
  668.         case DrawingStyle of
  669.         bhsDefault :
  670.           DrawFrameControl(bhDraw.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONPUSH);
  671.         bhsThin :
  672.           DrawEdge(bhDraw.Canvas.Handle, R, EDGE_ETCHED, BF_BOTTOM or BF_TOP or BF_LEFT or BF_RIGHT or BF_MIDDLE);
  673.         bhsFlat :
  674.           begin
  675.             inc(R.Right, 2);
  676.             DrawEdge(bhDraw.Canvas.Handle, R, EDGE_ETCHED, BF_BOTTOM or BF_TOP or BF_LEFT or BF_RIGHT or BF_MIDDLE);
  677.             dec(R.Right, 2);
  678.           end;
  679.         bhsEtched :
  680.           begin
  681.             inc(R.Right, 2);
  682.             DrawEdge(bhDraw.Canvas.Handle, R, EDGE_ETCHED, BF_BOTTOM or BF_TOP or BF_MIDDLE);
  683.             dec(R.Right, 2);
  684.             if (I <= FSections.Count) and ((FItemIndex <> I) or (Style <> bhsRadio)) then begin
  685.               Pen.Color := clBtnShadow;
  686.               MoveTo(R.Right - 2, R.Top + 3);
  687.               LineTo(R.Right - 2, R.Bottom - 3);
  688.               Pen.Color := clBtnHighlight;
  689.               MoveTo(R.Right - 1, R.Top + 3);
  690.               LineTo(R.Right - 1, R.Bottom - 3);
  691.             end;
  692.             if I = 1 then begin
  693.               Pen.Color := clBtnShadow;
  694.               MoveTo(R.Left, R.Top + 1);
  695.               LineTo(R.Left, R.Bottom - 1);
  696.               Pen.Color := clBtnHighlight;
  697.               MoveTo(R.Left + 1, R.Top + 1);
  698.               LineTo(R.Left + 1, R.Bottom - 2);
  699.             end;
  700.             if I > FSections.Count then begin
  701.               Pen.Color := clBtnShadow;
  702.               MoveTo(R.Right - 1, R.Top + 1);
  703.               LineTo(R.Right - 1, R.Bottom - 1);
  704.             end;
  705.           end;
  706.         end;
  707.         {$ELSE}
  708.         DrawButtonFrame(bhDraw.Canvas,R,False,False,bsNew);
  709.         {$ENDIF}
  710.       end else begin
  711.         {$IFDEF WIN32}
  712.         case DrawingStyle of
  713.         bhsDefault :
  714.           DrawFrameControl(Handle, R, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED);
  715.         bhsThin :
  716.           DrawEdge(bhDraw.Canvas.Handle, R, EDGE_ETCHED, BF_BOTTOM or BF_TOP or BF_LEFT or BF_RIGHT or BF_MIDDLE);
  717.         bhsFlat :
  718.           begin
  719.             inc(R.Right, 2);
  720.             DrawEdge(bhDraw.Canvas.Handle, R, EDGE_ETCHED, BF_BOTTOM or BF_TOP or BF_LEFT or BF_RIGHT or BF_MIDDLE);
  721.             dec(R.Right, 2);
  722.           end;
  723.         bhsEtched :
  724.           begin
  725.             inc(R.Right, 2);
  726.             DrawEdge(bhDraw.Canvas.Handle, R, EDGE_ETCHED, BF_BOTTOM or BF_TOP or BF_MIDDLE);
  727.             dec(R.Right, 2);
  728.             if I <= FSections.Count then begin
  729.               Pen.Color := clBtnShadow;
  730.               MoveTo(R.Right - 2, R.Top + 3);
  731.               LineTo(R.RIght - 2, R.Bottom - 3);
  732.               Pen.Color := clBtnHighlight;
  733.               MoveTo(R.Right - 1, R.Top + 3);
  734.               LineTo(R.RIght - 1, R.Bottom - 3);
  735.             end;
  736.             if I = 1 then begin
  737.               Pen.Color := clBtnShadow;
  738.               MoveTo(R.Left, R.Top + 1);
  739.               LineTo(R.Left, R.Bottom - 1);
  740.               Pen.Color := clBtnHighlight;
  741.               MoveTo(R.Left + 1, R.Top + 1);
  742.               LineTo(R.Left + 1, R.Bottom - 2);
  743.             end;
  744.             if I > FSections.Count then begin
  745.               Pen.Color := clBtnShadow;
  746.               MoveTo(R.Right - 1, R.Top + 1);
  747.               LineTo(R.Right - 1, R.Bottom - 1);
  748.             end;
  749.           end;
  750.         end;
  751.         {$ELSE}
  752.         DrawButtonFrame(bhDraw.Canvas,R,True{False},False{True},bsNew);
  753.         {$ENDIF}
  754.       end;
  755.  
  756.       {$IFNDEF WIN32}
  757.       TextRect(Rect(R.Left+1, R.Top+1, R.Right-1, R.Bottom-1), R.Left+3, Y, '');
  758.       {$ENDIF}
  759.  
  760.       if FWordWrap then
  761.         WM := DT_WORDBREAK
  762.       else
  763.         WM := DT_VCENTER or DT_SINGLELINE;
  764.  
  765.       R2 := Rect(R.Left+2, R.Top+2, R.Right-4, R.Bottom-1);
  766.  
  767.       if (Images <> nil) and (Img <> -1) then begin
  768.         BDim.x := Images.Width;
  769.         BDim.y := Images.Height;
  770.         if (BDim.x <> 0) and (BDim.y <> 0) then begin
  771.           dec(R2.Right,BDim.X + 2);
  772.           H := R2.Bottom-R2.Top;
  773.           if H <= BDim.y then
  774.             T := R2.Top
  775.           else
  776.             T := R2.Top + (H - BDim.y) shr 1;
  777.           Images.Draw(bhDraw.Canvas,R2.Right + 2,T,Img);
  778.         end;
  779.       end;
  780.  
  781.       if TextMargin < (R2.Right-R2.Left) div 2 then
  782.         InflateRect(R2, -TextMargin, 0);
  783.  
  784.       if S <> '' then begin
  785.         if not WordWrap then
  786.           S := GetDisplayString(bhDraw.Canvas,S,1,R2.Right-R2.Left);
  787.         StrPCopy(P,S);
  788.         DoOnChangeTextAttr(bhDraw.Canvas,I-1);
  789.       end else
  790.         StrCopy(P,'');
  791.       DrawText(Handle, @P, StrLen(@P), R2, AL or WM);
  792.  
  793.     until R.Right = ClientWidth;
  794.   end;
  795.   Canvas.CopyMode := cmSrcCopy;
  796.   Canvas.CopyRect(ClientRect, bhDraw.Canvas, ClientRect);
  797. end;
  798.  
  799. procedure TOvcButtonHeader.SetBorderStyle(Value : TBorderStyle);
  800. begin
  801.   if (Value <> FBorderStyle) then begin
  802.     FBorderStyle := Value;
  803.     RecreateWnd;
  804.   end;
  805. end;
  806.  
  807. {$IFDEF Win32}
  808. procedure TOvcButtonHeader.SetDrawingStyle(
  809.   const Value: TOvcBHDrawingStyle);
  810. begin
  811.   FDrawingStyle := Value;
  812.   Refresh;
  813. end;
  814. {$ENDIF}
  815.  
  816. procedure TOvcButtonHeader.SetImages(Value : TImageList);
  817. begin
  818.   if Value <> FImages then begin
  819.     if FImages <> nil then
  820.       FImages.OnChange := nil;
  821.     FImages := Value;
  822.     if FImages <> nil then
  823.       FImages.OnChange := bhCollectionChanged;
  824.     Refresh;
  825.   end;
  826. end;
  827.  
  828. procedure TOvcButtonHeader.SetItemIndex(Value : Integer);
  829. begin
  830.   if (Value <> FItemIndex) and (Value < FSections.Count) then begin
  831.     FItemIndex := Value;
  832.     DoOnClick;
  833.   end;
  834. end;
  835.  
  836. procedure TOvcButtonHeader.SetSection(Index: Integer; Value: TOvcButtonHeaderSection);
  837. begin
  838.   FSections[Index] := Value;
  839. end;
  840.  
  841. procedure TOvcButtonHeader.SetStyle(Value : TOvcButtonHeaderStyle);
  842. begin
  843.   if (Value <> FStyle) then begin
  844.     FStyle := Value;
  845.     Refresh;
  846.   end;
  847. end;
  848.  
  849. procedure TOvcButtonHeader.SetTextMargin(Value : Integer);
  850. begin
  851.   if (Value <> FTextMargin) and (Value >= 0) then begin
  852.     FTextMargin := Value;
  853.     Refresh;
  854.   end;
  855. end;
  856.  
  857. procedure TOvcButtonHeader.SetWordWrap(Value : Boolean);
  858. begin
  859.   if (Value <> FWordWrap) then begin
  860.     FWordWrap := Value;
  861.     Refresh;
  862.   end;
  863. end;
  864.  
  865. procedure TOvcButtonHeader.WMNCHitTest(var Msg : TWMNCHitTest);
  866. begin
  867.   inherited;
  868.  
  869.   bhHitTest := SmallPointToPoint(Msg.Pos);
  870. end;
  871.  
  872. procedure TOvcButtonHeader.WMSetCursor(var Msg : TWMSetCursor);
  873. var
  874.   Cur : hCursor;
  875.   I   : Integer;
  876.   X   : Integer;
  877. begin
  878.   Cur := 0;
  879.   bhResizeSection := 0;
  880.   bhHitTest := ScreenToClient(bhHitTest);
  881.   X := 2;
  882.   if Msg.HitTest = HTCLIENT then
  883.     for I := 0 to FSections.Count - 1 do begin
  884.       Inc(X, Section[I].Width);
  885.       bhMouseOffset := X - (bhHitTest.X + 2);
  886.       if Abs(bhMouseOffset) < 4 then begin
  887.         Cur := LoadCursor(0, IDC_SIZEWE);
  888.         bhResizeSection := I;
  889.         Break;
  890.       end;
  891.     end;
  892.  
  893.   bhCanResize := (FAllowResize or (csDesigning in ComponentState)) and (Cur <> 0);
  894.   if bhCanResize then begin
  895.     SetCursor(Cur);
  896.     Msg.Result := 1;
  897.   end else
  898.     inherited;
  899. end;
  900.  
  901. end.
  902.